from django.db import models

import core.models
import core.url

import datetime
import re
import urllib2
from xml.dom import minidom

class Security(core.models.BaseModel):
  
  class SymbolInvalidError(Exception):
    pass
  
  # By default, how often we refresh the data
  DEFAULT_REFRESH_TIME = datetime.timedelta(minutes=15)
  
  symbol = models.CharField(primary_key=True, max_length=10)
  
  # Security details, changes rarely
  company = models.CharField(blank=True, max_length=255)
  exchange = models.CharField(blank=True, max_length=255)
  currency = models.CharField(blank=True, max_length=10)
  
  # Cached data, changes frequently
  refreshed_at = models.DateTimeField(null=True)
  last = models.FloatField(null=True)
  high = models.FloatField(null=True)
  low = models.FloatField(null=True)
  volume = models.FloatField(null=True)
  market_cap = models.FloatField(null=True)
  open = models.FloatField(null=True)
  y_close = models.FloatField(null=True)
  change = models.FloatField(null=True)
  perc_change = models.FloatField(null=True)
  
  @staticmethod
  def getFromSymbol(symbol):
    symbol = symbol.upper()
    if not re.match('^[A-Z0-9.]+$', symbol):
      raise Security.SymbolInvalidError(
        'Symbol %s contains invalid characters' % symbol)
    try:
      security = Security.objects.get(pk=symbol)
    except Security.DoesNotExist:
      security = Security(symbol=symbol)
    if security.needsRefresh():
      security = security.refresh()
    return security
  
  def getSummaryUrl(self):
    return core.url.URL('/s/%s/' % self.symbol)
  
  def needsRefresh(self, refresh_time=None):
    if self.refreshed_at is None:
      return True
    if not isinstance(refresh_time, datetime.timedelta):
      refresh_time = Security.DEFAULT_REFRESH_TIME
    since_refresh = datetime.datetime.now() - self.refreshed_at
    return since_refresh >= refresh_time
  
  def refresh(self):
    url = 'http://www.google.com/ig/api?stock=%s' % self.symbol
    xml = urllib2.urlopen(url)
    dom = minidom.parse(xml)
    # Check if the symbol was valid
    # NB: Assumes all valid symbols will have a company name. Is this true?
    elems = dom.getElementsByTagName('company')
    if not elems or not elems[0].getAttribute('data'):
      raise Security.SymbolInvalidError('Symbol %s is not listed' % self.symbol)
    self.refreshed_at = datetime.datetime.now()
    attrs = [
      'company', 'exchange', 'currency',
      'last', 'high', 'low', 'volume', 'market_cap', 'open',
      'y_close', 'change', 'perc_change',
    ]
    for var in attrs:
      elems = dom.getElementsByTagName(var)
      if elems and elems[0].getAttribute('data'):
        setattr(self, var, elems[0].getAttribute('data'))
    self.save()
    return self
    